package com.jichaoyun.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jichaoyun.common.enums.MyExceptiontType;
import com.jichaoyun.common.ex.MyException;
import com.jichaoyun.model.entity.StationInfo;

import com.jichaoyun.common.model.PagedResult;
import com.jichaoyun.model.entity.RealdataCache;

import com.jichaoyun.model.entity.User;
import com.jichaoyun.sys.mapper.RealdataCacheMapper;
import com.jichaoyun.sys.mapper.RealdataMapper;
import com.jichaoyun.sys.mapper.StationInfoMapper;
import com.jichaoyun.sys.mapper.UserMapper;
import com.jichaoyun.sys.service.IRealdataCacheService;
import com.jichaoyun.sys.service.IStationInfoService;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
* @author zhen
* @description 针对表【realData_cache】的数据库操作Service实现
* @createDate 2023-12-20 15:25:03
*/
@Service("App_RealdataCacheServiceImpl")
public class RealdataCacheServiceImpl extends ServiceImpl<RealdataCacheMapper, RealdataCache>
    implements IRealdataCacheService {

    @Resource
    private StationInfoMapper stationInfoMapper;

    @Resource
    private IStationInfoService stationInfoService;

    @Resource
    private UserMapper userMapper;

    @Resource
    private RealdataMapper realdataMapper;

    @Override
    public RealdataCache getStationSingleInfoById(Integer station_no) {

        return this.baseMapper.getStationSingleInfoById(station_no);
    }

    /**
     * 获取该站点的实时流量,压力，温度，频率
     * @param station_no
     * @return
     */
    @Override
    public List<Map<String, Object>> getRealDataById(Integer station_no) {
        return this.baseMapper.getRealDatabyId(station_no);
    }

    /**
     * 实时流量top5
     * @return
     */
    @Override
    public List<RealdataCache> getTop5Flow(Integer userId) {
        User user = this.userMapper.selectById(userId);
        List<RealdataCache> datalist;

        if (user.getUserRole() == 0){
            datalist =  this.baseMapper.selectTop5FlowSelf(userId);
        }else {
            datalist =  this.baseMapper.selectTop5Flow();
        }

        //加上名称字段
        return getRealdataCache(datalist);
    }

    /**
     * 实时温度top5
     * @return
     */
    @Override
    public List<RealdataCache> getTop5Temp(Integer userId) {
        User user = this.userMapper.selectById(userId);
        List<RealdataCache> datalist;

        if (user.getUserRole() == 0){
            datalist =  this.baseMapper.selectTop5TempSelf(userId);
        }else {
            datalist =  this.baseMapper.selectTop5Temp();
        }
        return getRealdataCache(datalist);
    }

    /**
     * 实时压力top5
     * @return
     */
    @Override
    public List<RealdataCache> getTop5Pres(Integer userId) {
        User user = this.userMapper.selectById(userId);
        List<RealdataCache> datalist;

        if (user.getUserRole() == 0){
            datalist =  this.baseMapper.selectTop5PresSelf(userId);
        }else {
            datalist =  this.baseMapper.selectTop5Pres();
        }
        return getRealdataCache(datalist);
    }

    /**
     * 查询多用户实时信息
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public PagedResult getMultiRealInfovo(Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo,pageSize);
        List<RealdataCache> multiRealInfoList = this.baseMapper.getMultiRealInfo();

        for (int i=0;i<multiRealInfoList.size();i++) {
            RealdataCache multiRealInfo = multiRealInfoList.get(i);
            Integer station = multiRealInfo.getStation();
            LambdaQueryWrapper<StationInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(StationInfo::getStationNo,station);
            StationInfo staObject = stationInfoMapper.selectOne(wrapper);
            if(staObject == null){
                throw new MyException(MyExceptiontType.Other,null);
//                multiRealInfo.setStationName("未知站点错误");
            }else {
                multiRealInfo.setStationName(staObject.getStationName());
            }
        }
        PageInfo<RealdataCache> pagelist = new PageInfo<>(multiRealInfoList);
        PagedResult result = new PagedResult();
        result.setTotal((int) pagelist.getTotal());
        result.setPages(pagelist.getPages());
        result.setRows(pagelist.getList());
        return result;
    }

    /**
     * 查询近30分钟数据
     * @param stationName
     * @return
     */
    @Override
    public Map<String, List<Object>> getHalfHourRealData(String stationName) {

        //获取当前时间 和 30分钟前的时间 并 格式化
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime end = LocalDateTime.now().withNano(0);
        LocalDateTime start = end.minusMinutes(30);

        //根据传入的站点名称找到站点id
        Map<String, List<Object>> result = new HashMap<>();
        LambdaQueryWrapper<StationInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StationInfo::getStationName,stationName.trim());
        Integer stationId = stationInfoService.getOne(wrapper).getStationNo();

        //只取最近的30条
        List<Float> flowList = new ArrayList<>();
        List<Float> tempList = new ArrayList<>();
        List<Float> presList = new ArrayList<>();
        List<Float> freqList = new ArrayList<>();
        List<String> timeList = new ArrayList<>();

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm");
        for(int i=0;i<30;i++){
            LambdaQueryWrapper<RealdataCache> queryWrapper = new LambdaQueryWrapper<>();
//            System.out.println(start);
//            System.out.println(start.plusSeconds(90));
            queryWrapper.ge(RealdataCache::getRecordTime,start)
                    .lt(RealdataCache::getRecordTime,start.plusSeconds(90))
                    .eq(RealdataCache::getStation,stationId)
                    .orderByAsc(RealdataCache::getRecordTime);
            List<RealdataCache> list = this.baseMapper.selectList(queryWrapper);
            if(list!=null && list.size()!=0){
                RealdataCache item = list.get(0);
                LocalDateTime time = item.getRecordTime();
                flowList.add(item.getFlow());
                tempList.add(item.getTemp());
                presList.add(item.getPres());
                freqList.add(item.getFreq());
                timeList.add(time.format(dateTimeFormatter));
            }else {
                flowList.add(0f);
                tempList.add(0f);
                presList.add(0f);
                freqList.add(0f);
                timeList.add(start.format(dateTimeFormatter));
            }
            start = start.plusSeconds(60);
        }
        result.put("近30分钟流量", Collections.singletonList(flowList));
        result.put("近30分钟温度", Collections.singletonList(tempList));
        result.put("近30分钟压力", Collections.singletonList(presList));
        result.put("近30分钟频率", Collections.singletonList(freqList));
        result.put("时间段", Collections.singletonList(timeList));

        return result;
    }

    public String calculateMinuteLossRareByStation(LocalDateTime time, Integer stationNo ,Float mainFlow){
        //查出其子节点表
        LambdaQueryWrapper<StationInfo> wp = new LambdaQueryWrapper<>();
        wp.eq(StationInfo::getFatherStationNo,stationNo);
        List<StationInfo> divStation= stationInfoMapper.selectList(wp);
        if(divStation == null || divStation.size()==0){
            return "0.00";
        }

        //计算分表的流量和
        Float div_f = 0f;
        LocalDateTime start1 = time.withSecond(0);
        LocalDateTime end1= time.withSecond(0).plusSeconds(59);
        for (StationInfo stationInfo : divStation) {
            LambdaQueryWrapper<RealdataCache> wrapper2 = new LambdaQueryWrapper<>();
            wrapper2.le(RealdataCache::getRecordTime,end1).ge(RealdataCache::getRecordTime,start1)
                    .eq(RealdataCache::getStation,stationInfo.getStationNo()).orderByDesc(RealdataCache::getRealId);
            RealdataCache one = this.baseMapper.selectOne(wrapper2);
            if (one == null){
                div_f+=0f;
            }else {
                div_f+=one.getFlow();
            }
        }

        return String.format("%.2f",(mainFlow-div_f)/mainFlow);

    }

    /**
     * 管损报表查询-查询右边的图
     * 查找最近十分钟的数据
     * @param stationNo
     * @return
     */
    @Override
    public Map<String, Object> getTenMinutesLineLossForm(Integer stationNo) {
        LocalDateTime start = LocalDateTime.now().minusMinutes(11);
        HashMap<String, Object> resMap = new HashMap<>();
        LocalDateTime end = LocalDateTime.now();
        LambdaQueryWrapper<RealdataCache> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.le(RealdataCache::getRecordTime,end).ge(RealdataCache::getRecordTime,start)
                .eq(RealdataCache::getStation,stationNo).orderByDesc(RealdataCache::getRealId);
        List<RealdataCache> realdataList = this.baseMapper.selectList(wrapper2);
        int i  = 0;
        for (RealdataCache realdata : realdataList) {
            if(i==10) {
                break;
            }
            LocalDateTime time = realdata.getRecordTime();
            String loss = calculateMinuteLossRareByStation(time, stationNo, realdata.getFlow());

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
            // 格式化时间
            String formattedTime = time.format(formatter);

            resMap.put(formattedTime,loss);
            i++;

        }

        return resMap;
    }



    /**
     * 主要是给realdata的站名赋值
     */
    private List<RealdataCache> getRealdataCache(@NotNull List<RealdataCache> datalist) {
        for (RealdataCache realdata : datalist) {
            Integer station_no = realdata.getStation();
            LambdaQueryWrapper<StationInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(StationInfo::getStationNo,station_no);
            String station_name =  stationInfoMapper.selectOne(lambdaQueryWrapper).getStationName();
            realdata.setStationName(station_name);
        }
        return datalist;
    }
}




